package com.yihaodian.cluster;

import java.util.Collection;

import com.yihaodian.index.meta.IndexMetas;
import com.yihaodian.index.meta.routing.RoutingTables;

/**
 * 0) node list 1) routing table 2) meta (schema/data version)
 */
public class ClusterState {
	/**
	 * version of cluster state
	 */
	final long version;

	/**
	 * nodes list
	 */
	final Cluster cluster;

	/**
	 * routing table
	 */
	final RoutingTables routingTables;

	/**
	 * index meta
	 */
	final IndexMetas indexMetas;

	public ClusterState(long version, Cluster cluster,
			RoutingTables routingTables, IndexMetas indexMetas) {
		this.version = version;
		this.cluster = cluster;
		this.routingTables = routingTables;
		this.indexMetas = indexMetas;
	}

	public Node masterNode() {
		return cluster.getMaster();
	}

	public Collection<Node> nodes() {
		return cluster.getNodes();
	}

	public RoutingTables routingTables() {
		return routingTables;
	}

	public IndexMetas indexMetas() {
		return indexMetas;
	}

	public long version() {
		return version;
	}

	public static class Builder {
		long version = 0;
		Cluster cluster = null;
		RoutingTables routingTables = null;
		IndexMetas indexMetas;

		public Builder() {
			// empty
			cluster = new Cluster.Builder().build();
			routingTables = new RoutingTables.Builder().build();
			indexMetas = new IndexMetas.Builder().build();
		}

		public Builder(ClusterState cs) {
			if (cs == null){
				return;
			}		

			this.version = cs.version + 1;
			this.cluster = new Cluster.Builder(cs.cluster).build();
			this.routingTables = new RoutingTables.Builder(cs.routingTables)
					.build();
			this.indexMetas = new IndexMetas.Builder(cs.indexMetas).build();
		}

		public Builder version(long version) {
			this.version = version;

			return this;
		}

		public Builder cluster(Cluster cluster) {
			this.cluster = cluster;

			return this;
		}

		public Builder routingTables(RoutingTables routingTables) {
			this.routingTables = routingTables;

			return this;
		}

		public Builder indexMetas(IndexMetas indexMetas) {
			this.indexMetas = indexMetas;

			return this;
		}

		public ClusterState build() {
			return new ClusterState(version, cluster, routingTables, indexMetas);
		}
	}
}
